#include <iostream>
#include <thread>
#include <vector>
#include <string>
#include "conCurrentAlloc.h"
 
#ifdef _CURNEW
void* operator new(size_t size)
{
  std::cerr << "operator new..."<< size << std::endl;
  void* ptr = cAlloc(size);
  if(ptr == nullptr)
    throw std::bad_alloc();

  return ptr;
}

void operator delete(void* ptr)
{
  std::cerr << "operator delete..." << ptr << std::endl;
  cFree(ptr);
}
#endif

void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	size_t malloc_costtime = 0;
	size_t free_costtime = 0;
 
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&, k]() {
			std::vector<int*> v;
			v.reserve(ntimes);
 
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					v.push_back(new int);
          std::cout << "BenchmarkMalloc:alloc " << v[i] << std::endl;
				}
				size_t end1 = clock();
 
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
          std::cout << "BenchmarkMalloc:delete " << v[i] << std::endl;
          if(v[i] == nullptr)
          {
          std::cout << "BenchmarkMalloc:delete nullptr " << i << ":" << pthread_self() << std::endl;
          }
					delete v[i];
				}
				size_t end2 = clock();
				v.clear();
 
				malloc_costtime += end1 - begin1;
				free_costtime += end2 - begin2;
			}
		});
	}
 
	for (auto& t : vthread)
	{
		t.join();
	}
 
	printf("%u个线程并发执行%u轮次，每轮次malloc %u次: 花费：%u ms\n",
		nworks, rounds, ntimes, malloc_costtime);
 
	printf("%u个线程并发执行%u轮次，每轮次free %u次: 花费：%u ms\n",
		nworks, rounds, ntimes, free_costtime);
 
	printf("%u个线程并发malloc&free %u次，总计花费：%u ms\n",
		nworks, nworks*rounds*ntimes, malloc_costtime + free_costtime);
}
 
 
// 单轮次申请释放次数 线程数 轮次
void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	size_t malloc_costtime = 0;
	size_t free_costtime = 0;
 
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&]() {
			std::vector<void*> v;
			v.reserve(ntimes);
 
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					v.push_back(cAlloc(16));
          //*v[i] = 9;
          //std::cout << *v[i];
				}
				size_t end1 = clock();
 
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
          if(v[i])
          {
            //std::cout << "free "<< v[i] << "----"<<std::endl;
					  cFree(v[i]);
				  }
        }
				size_t end2 = clock();
				v.clear();
 
				malloc_costtime += end1 - begin1;
				free_costtime += end2 - begin2;
			}
		});
	}
 
	for (auto& t : vthread)
	{
		t.join();
	}
 
	printf("%u个线程并发执行%u轮次，每轮次concurrent alloc %u次: 花费：%u ms\n",
		nworks, rounds, ntimes, malloc_costtime);
 
	printf("%u个线程并发执行%u轮次，每轮次concurrent dealloc %u次: 花费：%u ms\n",
		nworks, rounds, ntimes, free_costtime);
 
	printf("%u个线程并发concurrent alloc&dealloc %u次，总计花费：%u ms\n",
		nworks, nworks*rounds*ntimes, malloc_costtime + free_costtime);
}
 
int main()
{
  std::string p = "../log/server.log";
  COM::logger = (qLogger*)malloc(sizeof(qLogger));
  new (COM::logger) qLogger(p);
	std::cout << "==========================================================" << std::endl;
	BenchmarkMalloc(10000, 5, 10);
	std::cout << std::endl << std::endl;
 
	//BenchmarkConcurrentMalloc(10000, 5, 100);
	std::cout << "==========================================================" << std::endl;
  //线程本地存储实现了，但是空间释放，和获取span有问题，可能是空间申请有问题，用回new和delete
 
	return 0;
}

// #include <iostream>
// #include "conCurrentAlloc.h"

// class A
// {
// private:
// public:
  // int a_;
  // int b_;
  // int c_;
  // int d_;
  // void print()
  // {
    // std::cout << a_ << ":" << b_;
    // std::cout << c_ << ":" << d_ << std::endl;
  // }
// };

// int main()
// {
  // int* a = (int*)Alloc(int());
  // *a = 1;
  // std::cout << a << ":" << *a << std::endl;
  // int* b = (int*)Alloc(int());
  // *b = 2;
  // std::cout << b << ":" << *b << std::endl;
  // int* c = (int*)Alloc(int());
  // *c = 3;
  // std::cout << c << ":" << *c << std::endl;

  // Free(a);
  // Free(b);
  // Free(c);

  // return 0;
// }

//#include "mallocCommon.h"
//
//int main()
//{
//  OBJECT::heapAllocator<Span, 10> al;
//  al.print();
//
//  Span* sp1 = al.allocate();
//  std::cout << sp1 << "-----" << std::endl;
//  al.print();
//
//  Span* sp2 = al.allocate();
//  std::cout << sp2 << "-----" << std::endl;
//  al.print();
//
//  Span* sp3 = al.allocate();
//  std::cout << sp3 << "-----" << std::endl;
//  al.print();
//
//  std::cout << "===========" << std::endl;
//  al.deallocate(sp1);
//  al.print();
//
//  al.deallocate(sp2);
//  al.print();
//
//  al.deallocate(sp3);
//  al.print();
//
//  return 0;
//}
